package com.yuan.util.string;

import org.apache.commons.codec.binary.Base64;

import java.util.Collection;
import java.util.Iterator;
import java.util.UUID;

/**
 * 字符串工具类
 * @author YouYuan
 * @version 1.0
 */
public class StrUtil {

    public static final Base64 BASE64_CODER = new Base64();

    /**
     * 格式化字符串强制在一行内，这会去除所有换行符
     *
     * @param obj
     * @return
     */
    public static String formatStrInLine(Object obj){
        String str = obj.toString();
		/*
		 * 在regex中"\\"表示一个"\"，在java中一个"\"也要用"\\"表示。
		 * 这样，前一个"\\"代表regex中的"\"，后一个"\\"代表java中的"\"。
		 * 所以要想使用replaceAll方法将字符串中的反斜杠("\")替换成空字符串("")，则需要这样写：str.replaceAll("\\\\","");
		 */
        str = str.replaceAll("[(\r\n)|(\n)]+|(\\\\r\\\\n)+", "");
        return str;
    }

    /**
     * 判断字符串是否为空，非String对象会调用toString转换为字符串之后再判断
     * @param str
     * @return
     */
    public static boolean isEmpty(Object str) {
        return str == null || str.toString().length() == 0;
    }

    /**
     * 将字符串循环n次
     * @param str
     * @param num
     * @return
     */
    public static String cycleStr(String str, int num) {
        StringBuilder rs = new StringBuilder(str);
        for (int i = 1; i < num; ++i) {
            rs.append(str);
        }
        return rs.toString();
    }

    /**
     * 判断字符串str是否在字符串数组datas中存在
     * @param str
     * @param datas
     * @return
     */
    public static boolean strIn(String str, String... datas) {
        if (datas == null) {
            return false;
        }
        for (String data:datas) {
            if (data == str) {
                return true;
            }
            if (str != null && str.equals(data)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断字符串str是否在字符串数组datas中存在,忽略大小写
     * @param str
     * @param datas
     * @return
     */
    public static boolean strInIgnoreCase(String str, String... datas) {
        if (datas == null) {
            return false;
        }
        for (String data:datas) {
            if (data == str) {
                return true;
            }
            if (str != null && str.equalsIgnoreCase(data)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 生成新的uuid
     * @return
     */
    public static String uuid(){
        String s = UUID.randomUUID().toString();
        return s.replace("-", "").toUpperCase();
    }

    /**
     * 去除字符串前后空白字符
     * @param str
     * @return
     */
    public static String trim(String str) {
        return isEmpty(str) ? "" : str.trim();
    }

    /**
     * 去除字符串前后的空白字符，若字符串为空则返回给定的默认值
     * @param val
     * @param defaultVal
     * @return
     */
    public static String trim(Object val, String defaultVal) {
        if (isEmpty(val)) {
            return defaultVal;
        }
        return val.toString().trim();
    }

    /**
     * 对象转换成字符串并去除前后空格，若对象为null返回空字符串
     * @param val
     * @return
     */
    public static String trim(Object val) {
        if (val == null) {
            return "";
        }
        String s = val.toString();
        if (isEmpty(s)) {
            return "";
        }
        return s.trim();
    }

    /**
     * 将Base64编码的字符串转换成字节数组
     * @param base64Str
     * @return
     * @throws Exception
     */
    public static byte[] base64ToBytes(String base64Str) {
        if (isEmpty(base64Str)) {
            return null;
        }
        int index = base64Str.indexOf(',');
        if(index != -1){
            base64Str = base64Str.substring(index+1);
        }
        base64Str = base64Str.replace(" ", "+");//浏览器会自动将+转换成空格,这里要将其转换回来
        // Base64解码
        return BASE64_CODER.decode(base64Str.getBytes());
    }

    /**
     * 将byte数组编码为base64字符串
     * @param data
     * @return
     */
    public static String encodeBase64(byte[] data) {
        return new String(BASE64_CODER.encode(data));
    }

    /**
     * 将目标字符串以指定字符串结尾的字符替换为新的字符,若不是以指定字符结尾,则返回原字符串
     * @param data 原字符串
     * @param endStr 结尾字符串
     * @param newStr 替换的字符串
     * @return
     */
    public static String replaceEndStr(String data, String endStr, String newStr) {
        if (data != null && endStr != null) {
            if (data.endsWith(endStr)) {
                int index = data.lastIndexOf(endStr);
                return data.substring(0, index) + newStr;
            }
        }
        return data;
    }

    /**
     * 判断字符串是否包含指定的子串
     * @param data 字符串数据
     * @param target 子串
     * @return data为空或不包含返回false,包含返回true
     */
    public static boolean contain(String data, String target) {
        if (data == null) {
            return false;
        }
        return data.contains(target);
    }

    /**
     * 判断字符串是否包含任意给定的子串
     * @param data
     * @param targets
     * @return
     */
    public static boolean contains(String data, String... targets) {
        if (data == null || targets == null || targets.length == 0) {
            return false;
        }
        for (String t : targets) {
            if (data.contains(t)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断字符串是否包含任意给定的子串，匹配忽略大小写
     * @param data
     * @param targets
     * @return
     */
    public static boolean containsIgnoreCase(String data, String... targets) {
        if (data == null || targets == null || targets.length == 0) {
            return false;
        }
        String dataLower = data.toLowerCase();
        for (String t : targets) {
            String lowerCase = t.toLowerCase();
            if (data.contains(lowerCase)) {
                return true;
            }
        }
        return false;
    }

    public static boolean notEmpty(String str) {
        return !isEmpty(str);
    }

    /**
     * 将字符串按照指定的分隔符分割成子字符串数组
     * @param str 要分割的字符串
     * @param separator 分隔符
     * @return 分割后的字符串数组
     */
    public static String[] split(String str, String separator) {
        if (isEmpty(str)) {
            return new String[0];
        }
        return str.split(escapeRegexChars(separator));
    }

    /**
     * 将字符串中的正则特殊字符进行转义
     * 进行转义的字符有：'$', '(', ')', '*', '+', '.', '[', ']', '?', '\\', '^', '{', '}', '|'
     * @param str 需要进行转义的字符串
     * @return 转义后的字符串。
     */
    public static String escapeRegexChars(String str){
        if (isEmpty(str)) {
            return str;
        }
        return str.replace("\\", "\\\\").replace("*", "\\*")
                .replace("+", "\\+").replace("|", "\\|")
                .replace("{", "\\{").replace("}", "\\}")
                .replace("(", "\\(").replace(")", "\\)")
                .replace("^", "\\^").replace("$", "\\$")
                .replace("[", "\\[").replace("]", "\\]")
                .replace("?", "\\?").replace(",", "\\,")
                .replace(".", "\\.").replace("&", "\\&");
    }

    /**
     * 打印数组
     * @param arrs
     */
    public static void printArr(Object[] arrs) {
        for (int i = 0, len = arrs.length; i < len; i++) {
            Object o = arrs[i];
            if (i == 0) {
                System.out.print(o);
            } else {
                System.out.print("," + o);
            }
        }
        System.out.println();
    }

    /**
     * 对象调用toString转换成字符串，若对象为null则返回null
     * @param o
     * @return
     */
    public static String toStr(Object o) {
        if (o == null) {
            return null;
        }
        return o.toString();
    }

    /**
     * 筛选字符串中的字母和数字，其余所有字符将被忽略，返回筛选后的字符串
     * @param str
     * @return
     */
    public static String screenLetterAndNum(String str) {
        if (str == null) {
            return "";
        }
        char[] chars = str.toCharArray();
        StringBuilder strBf = new StringBuilder();
        strBf.setLength(0);
        for (int i = 0; i < chars.length; i++) {
            char c = chars[i];
            if (CharUtil.isNum(c) || CharUtil.isLetter(c)) {
                strBf.append(c);
            }
        }
        return strBf.toString();
    }

    /**
     * 判断两个字符串是否相同
     * @param a
     * @param b
     * @return
     */
    public static boolean equals(String a, String b){
        if (a == b) {
            return true;
        }
        if (a != null) {
            return a.equals(b);
        }
        return false;
    }

    /**
     * 判断两个字符串是否相同，忽略大小写
     * @param a
     * @param b
     * @return
     */
    public static boolean equalsIgnoreCase(String a, String b){
        if (a == b) {
            return true;
        }
        if (a != null) {
            return a.equalsIgnoreCase(b);
        }
        return false;
    }

    /**
     * 将字符序列连接成字符串
     * @param prefix 每个字符串的前缀
     * @param suffix 每个字符串的后缀
     * @param separator 字符串分隔符
     * @param elements 字符序列
     * @return
     */
    public static String join(String prefix, String suffix, String separator, CharSequence... elements) {
        if (elements == null || elements.length == 0) {
            return "";
        }
        if (prefix == null) {
            prefix = "";
        }
        if (suffix == null) {
            suffix = "";
        }
        if (separator == null) {
            separator = ",";
        }
        StringBuilder result = new StringBuilder();
        for (int i = 0, len = elements.length - 1; i <= len; i++) {
            result.append(prefix).append(elements[i]).append(suffix);
            if (i < len) {
                result.append(separator);
            }
        }
        return result.toString();
    }
    public static String join(CharSequence... elements) {
        return join(null, null, null, elements);
    }
    public static String join(String separator, CharSequence... elements) {
        return join(null, null, separator, elements);
    }

    /**
     * 将字符序列连接成字符串
     * @param prefix 每个字符串的前缀
     * @param suffix 每个字符串的后缀
     * @param separator 字符串分隔符
     * @param collection 字符序列
     * @return
     */
    public static String join(String prefix, String suffix, String separator, Collection collection) {
        if (collection == null || collection.size() == 0) {
            return "";
        }
        if (prefix == null) {
            prefix = "";
        }
        if (suffix == null) {
            suffix = "";
        }
        if (separator == null) {
            separator = ",";
        }
        StringBuilder result = new StringBuilder();
        Iterator iterator = collection.iterator();
        int len = collection.size() - 1;
        int i = 0;
        while (iterator.hasNext()) {
            Object o = iterator.next();
            String str = toStr(o);
            result.append(prefix).append(str).append(suffix);
            if (i < len) {
                result.append(separator);
            }
            i++;
        }
        return result.toString();
    }
}
